//
//  ViewController.m
//  RuntimeLearn
//
//  Created by 木槿科技 on 2018/4/4.
//  Copyright © 2018年 深圳市木槿科技有限公司. All rights reserved.
//

#import "ViewController.h"
#pragma 引入库文件
#import <objc/runtime.h>
#import <objc/message.h>
#import "CustomClass.h"
#import "TestClass.h"
@interface ViewController (){
    float myFloat;
    CustomClass *allobj;
}

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
//    [self copyObj];
//    [self objectDispose];
    
//    [self setClassTest];
    //[self getClassName];
    //[self oneParam];
    
    myFloat = 2.34f;
//    [self getClassAllMethod];
//    [self propertyNameList];
    //[self getInstanceVar];
    //[self getVarType];
    
    allobj = [CustomClass new];
    allobj.varTest1 = @"varTest1String";
    allobj.varTest2 = @"varTest2String";
    allobj.varTest3 = @"varTest3String";
    NSString *str = [self nameOfInstance:@"varTest1String"];
    NSLog(@"str:%@",str);
}

/**
 对象拷贝
 */
-(void)copyObj{
    CustomClass *obj = [CustomClass new];
    NSLog(@"对象拷贝:%p",&obj);
    //完全是一个新的对象
    id objTest = object_copy(obj,sizeof(obj));
    NSLog(@"%p", &objTest);
    [objTest fun1];
}

/**
 对象释放
 */
-(void)objectDispose{
    CustomClass *obj = [CustomClass new];
    (void)(NSLog(@"---%ld",obj.retainCount)),
    object_dispose(obj);
    //(void)(NSLog(@"---%ld",obj.retainCount)),
    //[obj release];
    //NSLog(@"---%ld",obj.retainCount);
    //[obj fun1];
    
    
}

/**
 更改对象的类
 */
-(void)setClassTest{
    CustomClass *obj = [CustomClass new];
    [obj fun1];
    
    Class aclass = object_setClass(obj, [CustomOtherClass class]);
    //obj 对象的类被更改了    swap the isa to an isa
    NSLog(@"aClass:%@",NSStringFromClass(aclass));
    NSLog(@"obj class:%@",NSStringFromClass([obj class]));
    [obj fun2];
}
-(void)getClassTest{
    CustomClass *obj = [CustomClass new];
    Class alogClass = object_getClass(obj);
    NSLog(@"--get:%@",NSStringFromClass(alogClass));
}
/**
 获取对象的类名
 */
- (void) getClassName{
    
    CustomClass *obj = [CustomClass new];
    NSString *className = [NSString stringWithCString:object_getClassName(obj) encoding:NSUTF8StringEncoding];
    NSLog(@"className:%@",className);
}
/**
 动态给一个类添加方法
 */
- (void)oneParam{
    TestClass *instance = [[TestClass alloc]init];
    //方法添加
    [instance performSelector:@selector(eatWithPersonName:) withObject:@"mujin"];
}

/**
 获取一个类所有方法
 */
-(void)getClassAllMethod{
    u_int count;
    Method *methods = class_copyMethodList([ViewController class], &count);
    for (int i = 0; i < count; i++) {
        SEL name = method_getName(methods[i]);
        NSString *strName = [NSString stringWithCString:sel_getName(name) encoding:NSUTF8StringEncoding];
        NSLog(@"strName:%@",strName);
    }
    
}

/**
 获取一个类的所有属性
 */
-(void)propertyNameList{
    u_int count;
    objc_property_t *properties = class_copyPropertyList([UIViewController class], &count);
    for (int i = 0; i < count; i++) {
        const char* propertyName = property_getName(properties[i]);
        NSString *strName = [NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding];
        NSLog(@"strName:%@",strName);
    }
}

/**
 获取全局变量的值
 */
-(void)getInstanceVar{
    float myFloatValue;
    object_getInstanceVariable(self, "myFloat", (void*)&myFloatValue);
    NSLog(@"myFloatValue:%f",myFloatValue);
}

/**
 判断某一个类的某一个属性的类型
 */
-(void)getVarType{
    CustomClass *obj = [CustomClass new];
    Ivar var = class_getInstanceVariable(object_getClass(obj), "varTest1");
    const char*typeEdcoding = ivar_getTypeEncoding(var);
    NSString *strName = [NSString stringWithCString:typeEdcoding encoding:NSUTF8StringEncoding];
    if ([strName hasPrefix:@"@"]) {
        NSLog(@"handle class case");
    }else if ([strName hasPrefix:@"i"]){
        NSLog(@"handle int case");
    }else if ([strName hasPrefix:@"f"]){
        NSLog(@"handle float case");
    }else{
        
    }
}

/**
 通过属性的值来获取其属性的名字（反射机制）
 */
-(NSString *)nameOfInstance:(id)instance{
    unsigned int numIvars =0;
    NSString *key=nil;
    Ivar * ivars = class_copyIvarList([CustomClass class], &numIvars);
    for(int i = 0; i < numIvars; i++) {
        Ivar thisIvar = ivars[i];
        const char *type =ivar_getTypeEncoding(thisIvar);
        NSString *stringType =  [NSString stringWithCString:type encoding:NSUTF8StringEncoding];
        //不是class就跳过
        if (![stringType hasPrefix:@"@"]) {
            continue;
        }
        //Reads the value of an instance variable in an object. object_getIvar这个方法中，当遇到非objective-c对象时，并直接crash
        if ((object_getIvar(allobj, thisIvar) == instance)) {
            
            // Returns the name of an instance variable.
            
            key = [NSString stringWithUTF8String:ivar_getName(thisIvar)];
            
            break;
            
        }
    }
    free(ivars);
    
    return key;
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end
